package com.sgcc.isc.service.impl;

import com.alibaba.druid.support.json.JSONUtils;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.sgcc.common.core.domain.R;
import com.sgcc.common.core.utils.DateUtils;
import com.sgcc.common.core.web.domain.AjaxResult;
import com.sgcc.common.core.web.page.TableDataInfo;
import com.sgcc.common.log.annotation.Log;
import com.sgcc.common.log.enums.BusinessType;
import com.sgcc.common.redis.service.RedisService;
import com.sgcc.isc.config.Global;
import com.sgcc.isc.domain.MonSysWsDto;
import com.sgcc.isc.domain.MonTarDataWsDto;
import com.sgcc.isc.domain.ResultMsg;
import com.sgcc.isc.domain.SpPortLog;
import com.sgcc.isc.exception.XmlStyleException;
import com.sgcc.isc.service.ISpPortLogService;
import com.sgcc.isc.service.MonitorService;
import com.sgcc.isc.util.XmlCreator;
import com.sgcc.isc.util.XmlParser;
import com.sgcc.isc.websocket.service.system.SystemInfoSocketHandler;
import com.sgcc.system.api.RemoteDictDataService;
import com.sgcc.system.api.RemoteJjrglService;
import com.sgcc.system.api.RemoteOAnomalyInfoService;
import com.sgcc.system.api.RemoteOMonTarService;
import com.sgcc.system.api.domain.OAnomalyInfo;
import com.sgcc.system.api.domain.OMonTar;
import com.sgcc.system.api.domain.SysDictData;
import org.codehaus.jackson.map.ObjectMapper;
import org.dom4j.DocumentException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.jws.WebService;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import java.beans.IntrospectionException;
import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;


@WebService(serviceName = "MonitorService")
@Component
public class MonitorServiceImpl implements MonitorService {


    @Autowired
    private RemoteOAnomalyInfoService remoteOAnomalyInfoServiceImpl;

    @Autowired
    private RemoteOMonTarService remoteOMonTarService;

    @Autowired
    private RemoteDictDataService remoteDictDataService;

    @Autowired
    private RemoteJjrglService remoteJjrglService;

    @Autowired
    private RedisService redisService;

    @Autowired
    private ISpPortLogService spPortLogService;

    @Override
    @Transactional
    @Log(title = "异常插入", businessType = BusinessType.INSERT)
    public String monitorInfo(String info) throws ParseException {
        Date startTime=new Date();
        MonSysWsDto monSys = null;
        ResultMsg resultMsg = new ResultMsg();
        ObjectMapper objectMapper = new ObjectMapper();
        SpPortLog spPortLog=new SpPortLog();
        spPortLog.setBgdate(startTime);
        spPortLog.setOcode(new BigDecimal(resultMsg.getRtnCode()));
        spPortLog.setImportMsg(info);
        spPortLog.setIsServer("01");
        spPortLog.setTdate(new Date());
        spPortLog.setJname("monitorInfo");
        try {
            // 解析xml
            monSys = (MonSysWsDto) XmlParser.parseXml2Entity(MonSysWsDto.class, info, null);
            System.out.println(monSys.toString());
        } catch (DocumentException e) {
            e.printStackTrace();
            resultMsg.setRtnCode("0");
            resultMsg.setRtnMessage("不是正规的xml格式字符串！");
            Date endTime=new Date();
            spPortLog.setOmsg("不是正规的xml格式字符串！");
            spPortLog.setEddate(endTime);
            spPortLogService.insertSpPortLog(spPortLog);
            return XmlCreator.resultXml(resultMsg);
        } catch (XmlStyleException e) {
            e.printStackTrace();
            resultMsg.setRtnCode("0");
            resultMsg.setRtnMessage(e.getMessage());
            Date endTime=new Date();
            spPortLog.setOmsg(e.getMessage());
            spPortLog.setEddate(endTime);
            spPortLogService.insertSpPortLog(spPortLog);
            return XmlCreator.resultXml(resultMsg);
        } catch (IllegalAccessException | InstantiationException |
                IntrospectionException | InvocationTargetException |
                NoSuchFieldException | ClassNotFoundException e) {
            e.printStackTrace();
            resultMsg.setRtnCode("0");
            resultMsg.setRtnMessage("系统错误！请联系系统管理员。");
            Date endTime=new Date();
            spPortLog.setOmsg("系统错误！请联系系统管理员。");
            spPortLog.setEddate(endTime);
            spPortLogService.insertSpPortLog(spPortLog);
            return XmlCreator.resultXml(resultMsg);
        }
        String xmldata = redisService.getCacheObject("monsys:xml:" + monSys.toString().hashCode());
        System.out.println(monSys.toString().hashCode());
        if (xmldata != null) {
            Date endTime=new Date();
            spPortLog.setOmsg("系统错误！禁止提交相同的数据,请联系系统管理员。");
            spPortLog.setEddate(endTime);
            spPortLogService.insertSpPortLog(spPortLog);
            resultMsg.setRtnMessage("禁止提交相同数据");
            return XmlCreator.resultXml(resultMsg);
        }

        redisService.setCacheObject("monsys:xml:" + monSys.toString().hashCode(), monSys.toString().hashCode() + "", 60L, TimeUnit.SECONDS);

        boolean socketseed = false;
        int monCodeError = 0, verdTypeError = 0, monStatusError = 0, outTimeError = 0;
        for (MonTarDataWsDto data : monSys.getMonList()) {


        	OAnomalyInfo anomalyInfo = createAnomalyInfo(data);
        	try {
        	
        	Date dataDate = anomalyInfo.getOccTime();
            // 过滤非当天数据
            if (null == dataDate || !DateUtils.formatDate(dataDate, "yyyy-MM-dd").equals(DateUtils.getDate())) {
                outTimeError ++;
                continue;
            }
//            remoteJjrglService
            
			} catch (Exception e) {
				// TODO: handle exception
				e.printStackTrace();
				continue;
			}
        	
//         // 根据monTarCode获取监控指标相关配置信息
            R<OMonTar> res = remoteOMonTarService.findCode(data.getMonTarCode());
//            // 无查询数据
            System.out.println(res.getData());
            if (null == res.getData()) {
                monCodeError ++;
                // 跳过
                continue;
            }
            String monStatus;
//            // 判断是预警还是异常
            OMonTar monTar=res.getData();
            if (Global.VERDTYPE_03.equals(monTar.getVerdType())) { // 预警
                monStatus = Global.MONSTATUS_03;
            } else if (Global.VERDTYPE_02.equals(monTar.getVerdType())) { // 异常
                monStatus = Global.MONSTATUS_02;
            } else {
                verdTypeError ++;
                continue;
            }
            /**
             * 01010501
             * 01010502
             * 01010503
             * 01010504
             * 是这五个时直接为异常
             */
            if("01010501".equals(data.getMonTarCode())||"01010502".equals(data.getMonTarCode())||"01010503".equals(data.getMonTarCode())||"01010504".equals(data.getMonTarCode())){
                socketseed = true;
                anomalyInfo.setMonStatus(Global.MONSTATUS_02);
                anomalyInfo.setStatus(Global.ANOMALYINFO_STATUS_01);
                remoteOMonTarService.editStatus(data.getMonTarCode(), anomalyInfo.getMonStatus());
                AjaxResult resOAnomalyInfo=remoteOAnomalyInfoServiceImpl.addAdminProcess(anomalyInfo);
                if("500".equals(resOAnomalyInfo.get("code").toString())) {
                    System.out.println(resOAnomalyInfo.get("msg"));
                    monStatusError ++;

                }
                continue;
            }

            if (Global.MONSTATUS_01.equals(anomalyInfo.getMonStatus())||
                    Global.MONSTATUS_03.equals(anomalyInfo.getMonStatus())) { // 监控状态 01 正常, 处理状态status 为空
            	SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            	TableDataInfo table=remoteJjrglService.findIsJjr(sdf.format(anomalyInfo.getOccTime()));
            	
            	if (table.getRows().size()>0&& Global.YES.equals(monTar.getOutHolidays())) {
                    continue;
                }
//                anomalyInfo.setDuration(new BigDecimal(0.0));
                JSONArray arr=JSONArray.parseArray(monTar.getOption());
                if(null!=arr&&arr.size()!=0&&!"04".equals(monTar.getStatWay())) {
                	StringBuffer str=new StringBuffer();
                	ScriptEngineManager manager = new ScriptEngineManager();
                	ScriptEngine engine = manager.getEngineByName("js");
//                	System.out.println(data.toString());
                	JSONObject monSysObj=JSONObject.parseObject(data.toString().toLowerCase());
                	int i=0;
                	for (Object object : arr) {
						JSONObject obj=JSONObject.parseObject(JSONUtils.toJSONString(object));
						String relationship=obj.getString("relationship");
						String statistics=obj.getString("statistics");
						String symbol=obj.getString("symbol");
						String value=obj.getString("value");
						String optionOrNumber=obj.getString("optionOrNumber");
						
						if(0!=i) {//当大于1条数据时最加关系||或者&&
							str.append(" "+relationship+" ");
						}
						i++;
						//传入第一个统计值 N_STAT
//						System.out.println("参数是："+statistics.toLowerCase());
						str.append(monSysObj.getDouble(statistics.toLowerCase()));
						//传入  符号 <  > != ==  >= <=
//						System.out.println("符号是："+symbol);
						str.append(symbol);
						//根据第一个参数传入数字参数
//						System.out.println();
//						engine.put(statistics, monSysObj.getDouble(statistics.toLowerCase()));
						if("01".equals(optionOrNumber)) {//如果是选项类型传入比对参数
							str.append(monSysObj.getDouble(value.toLowerCase()));
						}else {//如果是数字类型传入value的值
							str.append(value);
						}
						
						
						
					}
                	try {
                		System.out.println("计算语句："+str.toString());
						Object result = engine.eval(str.toString());
						System.out.println("结果类型:" + result.getClass().getName() + ",计算结果:" + result);
					
						anomalyInfo.setMonStatus((boolean) result?monStatus:anomalyInfo.getMonStatus());
					} catch (ScriptException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
						monStatusError++;
						 continue;
					}
                }
                AjaxResult resOAnomalyInfo=null;
                if(Global.MONSTATUS_02.equals(anomalyInfo.getMonStatus())){
                    anomalyInfo.setStatus(Global.ANOMALYINFO_STATUS_01);
                    anomalyInfo.setMonStatus(Global.MONSTATUS_02);
                    resOAnomalyInfo=remoteOAnomalyInfoServiceImpl.addAdminProcess(anomalyInfo);
                }else {
                    resOAnomalyInfo=remoteOAnomalyInfoServiceImpl.addAdmin(anomalyInfo);
                }
                remoteOMonTarService.editStatus(data.getMonTarCode(), anomalyInfo.getMonStatus());

                socketseed = true;


                if("500".equals(resOAnomalyInfo.get("code").toString())) {
                	System.out.println(resOAnomalyInfo.get("msg"));
                	 monStatusError ++;
                	 continue;
                }else {
                	System.out.println(resOAnomalyInfo.get("msg"));
                }
            } else if (Global.MONSTATUS_02.equals(anomalyInfo.getMonStatus()) ) { // 监控状态 02 异常 或者 03 预警
//                anomalyInfo.setMonStatus(monStatus);
                anomalyInfo.setMonStatus(Global.MONSTATUS_02);
                //socket 发送数据
                socketseed = true;

                // 插入表o_anomaly_info，status为01 待处理
                anomalyInfo.setStatus(Global.ANOMALYINFO_STATUS_01);
                // 添加发送信息
//                anomalyInfo.setSendMsg(getSendMsg(monTar, anomalyInfo.getMonStatus(), anomalyInfo.getMonMessage()));
                anomalyInfo.setDuration(null);
                // 修改o_mon_tar的对应数据为异常或预警
                remoteOMonTarService.editStatus(data.getMonTarCode(), Global.MONSTATUS_02);
                AjaxResult resOAnomalyInfo=remoteOAnomalyInfoServiceImpl.addAdminProcess(anomalyInfo);
                if("500".equals(resOAnomalyInfo.get("code").toString())) {
                	System.out.println(resOAnomalyInfo.get("msg"));
                	 monStatusError ++;
                	 continue;
                }
            } else { // 不匹配
                monStatusError ++;
            }
        }
        if(socketseed){
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("type",1);
            SystemInfoSocketHandler.sendMessageToAllUsers(jsonObject.toJSONString());
        }

        String str="监控状态编码错误或者网络错误" + monStatusError + "条，\n\r监控指标编码错误" + monCodeError + "条，\n\r判断类型编码错误"
                + verdTypeError + "条，\n\r过期数据" + outTimeError + "条,\n\r 成功" +
                (monSys.getMonList().size() - monCodeError - verdTypeError - monStatusError - outTimeError) + "条。";
        resultMsg.setRtnMessage(str);
        Date endTime=new Date();
        spPortLog.setOmsg(str);
        spPortLog.setEddate(endTime);
        spPortLogService.insertSpPortLog(spPortLog);
        return XmlCreator.resultXml(resultMsg);
    }
	private String time=DateUtils.dateTime();
	private OAnomalyInfo createAnomalyInfo(MonTarDataWsDto data) throws ParseException {

        Integer num=redisService.getCacheObject("isc:MonitorServiceImpl:createAnomalyInfo");
        if(null==num){
            num=0;
        }
        OAnomalyInfo anomalyInfo = new OAnomalyInfo();
        num++;
        if(!time.equals(DateUtils.dateTime())) {
            num=1;
            time=DateUtils.dateTime();
        }
        redisService.setCacheObject("isc:MonitorServiceImpl:createAnomalyInfo",num);
		NumberFormat f=new DecimalFormat("00000");
		String id=DateUtils.dateTimeNow()+f.format(num);
		anomalyInfo.setId(id);
        anomalyInfo.setMonid(data.getMonId());
        anomalyInfo.setMonSysCode(data.getMonSysCode());
        anomalyInfo.setMonType(data.getMonType());
        anomalyInfo.setMonTarCode(data.getMonTarCode());

        anomalyInfo.setOccTime(data.getOccTime());
        anomalyInfo.setMonMessage(data.getMonMessage());
        anomalyInfo.setnStat(null == data.getNStat() ? null : new BigDecimal(data.getNStat().toString()));
        anomalyInfo.setnStat2(null == data.getNStat2() ? null : new BigDecimal(data.getNStat2().toString()));
        anomalyInfo.setnStat3(null == data.getNStat3() ? null : new BigDecimal(data.getNStat3().toString()));
        anomalyInfo.setOrgNo(data.getOrgNo());
        anomalyInfo.setAreaNo(data.getAreaNo());
        anomalyInfo.setExtrField(data.getExtrField());
        anomalyInfo.setExtrField2(data.getExtrField2());
        anomalyInfo.setMonStatus(data.getMonStatus());
        return anomalyInfo;
    }
	
    private String getSendMsg(OMonTar monTar, String monStatus, String monMessage) {
    	ObjectMapper objectMapper = new ObjectMapper();
        String template = monTar.getSmsTemplate();
        AjaxResult res=remoteDictDataService.dictType("monStatus");
        List<SysDictData> dictValues=objectMapper.convertValue(res.get("data"),  List.class);
        String monStatusName = null;
        if(null!=dictValues) {
        	for (SysDictData dictValue : dictValues) {
                if (dictValue.getDictValue().equals(monStatus)) {
                    monStatusName = dictValue.getDictLabel();
                }
            }
        }
        AjaxResult resMonSysCode=remoteDictDataService.dictType("monSysCode");
        String monSysName = null;
        if(null!=resMonSysCode.get("data")) {
        	List<SysDictData> dictValuesMonSysCode=objectMapper.convertValue(resMonSysCode.get("data"),  List.class);
            if(null!=dictValues) {
            	for (SysDictData dictValue : dictValues) {
                    if (dictValue.getDictValue().equals(monTar.getMonSysCode())) {
                    	monSysName = dictValue.getDictLabel();
                    }
                }
            }
        }
        
        AjaxResult resMonType=remoteDictDataService.dictType("monType");
        List<SysDictData> dictValuesMonType=objectMapper.convertValue(resMonType.get("data"),  List.class);
        String monTypeName = null;
        if(null!=resMonSysCode.get("data")) {
	        if(null!=dictValues) {
	        	for (SysDictData dictValue : dictValues) {
	                if (dictValue.getDictValue().equals(monTar.getMonType())) {
	                	monTypeName = dictValue.getDictLabel();
	                }
	            }
	        }
        }
    
        return template
                .replaceAll("\\{监控编码}", monTar.getMonTarCode())
                .replaceAll("\\{监控系统}", monSysName)
                .replaceAll("\\{监控类型}", monTypeName)
                .replaceAll("\\{监控点}", monTar.getMonPoint())
                .replaceAll("\\{监控状态}", monStatusName)
                .replaceAll("\\{监控信息}", monMessage);
    }
 
}